﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CLFramework.Caching;
using System.Web;
using CLFramework.Infrastructure.PlugIns;
using CLFramework.Infrastructure.Validation;
using CLFramework.Data;
using System.Data.SqlClient;

namespace CLFramework.Infrastructure
{
    #region Delegates

    //public delegate void DeleteEntityDelegateWithModerationAudit<TEntity>(TEntity entity, ModerationAudit record, bool archive);
    //public delegate void DeleteEntityDelegate<TEntity>(TEntity entity);

    public delegate bool GetEntityKeyByOtherKeysDelegate<TKey>(object[] otherKeys, out TKey key);
    public delegate bool GetEntityKeyByAnotherKeyDelegate<TAnotherKey, TKey>(TAnotherKey anotherKey, out TKey key);

    public delegate List<TKey> GetEntityKeysDelegate<TKey, TEntityQuery>(TEntityQuery query) where TEntityQuery : EntityQuery;

    #endregion

    public class EntityManager<TKey, TEntity> where TEntity : class, IEntity<TKey>
    {
        #region Members

        string cacheKey = string.Format("EntityManager-{0}", typeof(TEntity).FullName);
        int cacheEntityDuration = 1800;
        int maxEntityCount = 30000;
        CacheEntityTable<TKey, TEntity> entitiesCache = null;
        PluginEngine pluginEngine;
        GetEntitiesFromDatabaseDelegate<TKey, TEntity> getEntitiesFromDatabase;

        #endregion

        #region ctor.

        public EntityManager(GetEntitiesFromDatabaseDelegate<TKey, TEntity> getEntitiesFromDatabase)
            : this(getEntitiesFromDatabase, null)
        { }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="getEntitiesFromDatabase">从数据库中获取实体集合的方法</param>
        /// <param name="pluginEngine">插件引擎</param>
        public EntityManager(GetEntitiesFromDatabaseDelegate<TKey, TEntity> getEntitiesFromDatabase, PluginEngine pluginEngine)
        {
            this.getEntitiesFromDatabase = getEntitiesFromDatabase;
            entitiesCache = CacheManager.GetCacheEntityTable<TKey, TEntity>(cacheKey, CacheEntityDuration, MaxEntityCount);
            this.pluginEngine = pluginEngine;
        }

        #endregion

        #region Properties

        /// <summary>
        /// 实体项缓存过期时间
        /// </summary>
        public int CacheEntityDuration
        {
            get { return cacheEntityDuration; }
            set { 
                cacheEntityDuration = value;
                entitiesCache.CacheEntityDuration = cacheEntityDuration;
            }
        }

        /// <summary>
        /// 最大缓存实体项数量
        /// </summary>
        public int MaxEntityCount
        {
            get { return maxEntityCount; }
            set { 
                maxEntityCount = value;
                entitiesCache.MaxEntityCount = maxEntityCount;
            }
        }

        /// <summary>
        /// 缓存集合
        /// </summary>
        public CacheEntityTable<TKey, TEntity> EntitiesCache
        {
            get { return entitiesCache; }
            set { entitiesCache = value; }
        }

        #endregion

        #region Methods

        #region Gets

        /// <summary>
        /// 获取单个实体
        /// </summary>
        /// <param name="key"></param>
        /// <param name="cacheable"></param>
        public TEntity GetEntity(TKey key, bool cacheable)
        {
            TEntity entity = default(TEntity);
            if (!cacheable ||
                !EntitiesCache.TryGetValue(key, out entity))
            {
                TKey[] entityIds = new TKey[] { key };
                List<TEntity> entities = GetEntities(entityIds, cacheable);
                if (entities != null && entities.Count == 1)
                {
                    entity = entities[0];
                }
            }
            return entity;
        }

        public TEntity GetEntityByOtherKey<TOtherKey>(TOtherKey otherKey, bool keyCacheable, bool cacheable
            , CacheEntityTable<TOtherKey, TKey> otherKeyToKeyCache
            , GetEntityKeyByAnotherKeyDelegate<TOtherKey, TKey> getEntityKeyByOtherKey
            , Func<TKey, bool, TEntity> getEntity
            )
        {
            if (otherKey == null)
                return default(TEntity);

            TEntity entity = default(TEntity);
            if (HttpContext.Current != null)
            {
                entity = GenericHelper.GenericCast<object, TEntity>(HttpContext.Current.Items[otherKey]);
                if (entity != null)
                    return entity;
            }

            TKey key = default(TKey);
            bool isEnityExists = false;
            if (keyCacheable && otherKeyToKeyCache.TryGetValue(otherKey, out key)) // 首先从Cache中查询
            {
                isEnityExists = true;
            }

            if (!isEnityExists) // 如果Cache中没有或者不从Cache中读取
            {
                if (getEntityKeyByOtherKey(otherKey, out key)) // 从数据库中查询Key
                {
                    otherKeyToKeyCache.Cache(otherKey, key); // 如果查询出来，插入Cache
                    isEnityExists = true;
                }
                else
                {
                    return entity; // 从数据库中查询失败
                }
            }

            if (isEnityExists)
            {
                entity = getEntity(key, cacheable);

                if (entity != null && HttpContext.Current != null)
                {
                    HttpContext.Current.Items[otherKey] = entity;
                }
            }

            return entity;
        }

        public TEntity GetEntityByOtherKeys(object[] otherKeys, bool keyCacheable, bool cacheable
            , CacheEntityTable<string, TKey> otherKeysToKeyCache
            , GetEntityKeyByOtherKeysDelegate<TKey> getEntityKeyByOtherKeys
            ,Func<TKey, bool, TEntity> getEntity
            , Func<object[], string> getCacheKey)
        {
            if (otherKeys == null || otherKeys.Length == 0)
                return default(TEntity);

            string cacheKey = getCacheKey(otherKeys);

            TEntity entity = default(TEntity);
            if (HttpContext.Current != null)
            {
                entity = GenericHelper.GenericCast<object, TEntity>(HttpContext.Current.Items[cacheKey]);
                if (entity != null)
                    return entity;
            } 

            TKey key = default(TKey); ;
            bool isEnityExists = false;
            if (keyCacheable && otherKeysToKeyCache.TryGetValue(cacheKey.ToString(), out key)) // 首先从Cache中查询
            {
                isEnityExists = true;
            }

            if (!isEnityExists) // 如果Cache中没有或者不从Cache中读取
            {
                if (getEntityKeyByOtherKeys(otherKeys, out key)) // 从数据库中查询Key
                {
                    otherKeysToKeyCache.Cache(cacheKey.ToString(), key); // 如果查询出来，插入Cache
                    isEnityExists = true;
                }
                else {
                    return entity; // 从数据库中查询失败
                }
            }

            if (isEnityExists)
            {
                entity = getEntity(key, cacheable);
                if (entity != null && HttpContext.Current != null)
                {
                    HttpContext.Current.Items[cacheKey.ToString()] = entity;
                }
            }

            return entity;
        }

        /// <summary>
        /// 根据Id集合获取实体集合
        /// </summary>
        /// <param name="entityIds">Id集合</param>
        /// <param name="entitiesCacheable">是否缓存</param>
        /// <returns></returns>
        public List<TEntity> GetEntities(TKey[] entityIds, bool entitiesCacheable)
        {
            Dictionary<TKey, TEntity> entities = new Dictionary<TKey, TEntity>();
            return GetEntities(entityIds, ref entities, entitiesCacheable);
        }

        /// <summary>
        /// 获取实体集合
        /// </summary>
        /// <param name="entityIds"></param>
        /// <param name="entitiesCacheable"></param>
        public List<TEntity> GetEntities(TKey[] entityIds
            , ref Dictionary<TKey, TEntity> entities, bool entitiesCacheable)
        {
            if (entities == null)
                entities = new Dictionary<TKey, TEntity>();

            return EntitiesCache.GetEntities(entityIds, ref entities, entitiesCacheable, getEntitiesFromDatabase);
        }

        /// <summary>
        /// 获取实体集合(哈希表)
        /// </summary>
        /// <param name="entityIds"></param>
        /// <param name="entitiesCacheable"></param>
        /// <returns></returns>
        public Dictionary<TKey, TEntity> GetEntitiesTable(TKey[] entityIds, bool entitiesCacheable)
        { 
            Dictionary<TKey, TEntity> entities = new Dictionary<TKey, TEntity>();
            EntitiesCache.GetEntities(entityIds, ref entities, entitiesCacheable, getEntitiesFromDatabase);
            return entities;
        }

        /// <summary>
        /// 根据父级实体的Key获取子级实体集合
        /// </summary>
        /// <typeparam name="TOtherKey">父级别实体Key的类型</typeparam>
        /// <param name="otherKey">父级别实体Key</param>
        /// <param name="keyCacheable">子实体Key是否缓存</param>
        /// <param name="otherKeyToKeysCache">父子实体Key之间关系缓存表</param>
        /// <param name="getEntityKeysByOtherKey">根据父实体Key获取子实体Key集合的代理</param>
        /// <param name="entities">子实体结果集</param>
        /// <param name="entitiesCacheable">子实体是否缓存</param>
        /// <returns></returns>
        public List<TEntity> GetEntitiesByOtherKey<TOtherKey>(TOtherKey otherKey, bool keyCacheable
            , CacheEntityTable<TOtherKey, List<TKey>> otherKeyToKeysCache
            , Func<TOtherKey, List<TKey>> getEntityKeysByOtherKey
            , ref Dictionary<TKey, TEntity> entities, bool entitiesCacheable)
        {
            if (otherKey == null)
                return default(List<TEntity>);

            List<TKey> keys = default(List<TKey>);
            bool isKeysExists = false;
            if (keyCacheable && otherKeyToKeysCache.TryGetValue(otherKey, out keys)) // 首先从Cache中查询Keys
            {
                isKeysExists = true;
            }

            if (!isKeysExists) // 如果Cache中没有Keys或者不从Cache中读取
            {
                keys = getEntityKeysByOtherKey(otherKey); // 从数据库中查询Keys

                if (keys != default(List<TKey>)) 
                {
                    otherKeyToKeysCache.Cache(otherKey, keys); // 如果查询出来，插入Cache
                    isKeysExists = true;
                }
                else
                {
                    return default(List<TEntity>); // 从数据库中查询失败
                }
            }

            if (isKeysExists)
            {
                return GetEntities(keys.ToArray(), ref entities, entitiesCacheable); //通过Keys查找实体集合
            }
            return default(List<TEntity>);
        }

        /// <summary>
        /// 根据父级实体的Key获取子级实体集合
        /// </summary>
        /// <typeparam name="TOtherKey">父级别实体Key的类型</typeparam>
        /// <param name="otherKey">父级别实体Key</param>
        /// <param name="keyCacheable">子实体Key是否缓存</param>
        /// <param name="otherKeyToKeysCache">父子实体Key之间关系缓存表</param>
        /// <param name="getEntityKeysByOtherKey">根据父实体Key获取子实体Key集合的代理</param>
        /// <param name="entitiesCacheable">子实体是否缓存</param>
        /// <returns></returns>
        public List<TEntity> GetEntitiesByOtherKey<TOtherKey>(TOtherKey otherKey, bool keyCacheable
            , CacheEntityTable<TOtherKey, List<TKey>> otherKeyToKeysCache
            , Func<TOtherKey, List<TKey>> getEntityKeysByOtherKey
            , bool entitiesCacheable)
        {
            Dictionary<TKey, TEntity> entities = new Dictionary<TKey, TEntity>();
            return GetEntitiesByOtherKey<TOtherKey>(otherKey, keyCacheable
                , otherKeyToKeysCache, getEntityKeysByOtherKey
                , ref entities, entitiesCacheable);
        }


        /// <summary>
        /// 根据多个参数集获取实体集合
        /// </summary>
        /// <param name="otherKeys">其它参数集合</param>
        /// <param name="keyCacheable">是否缓存Key结果</param>
        /// <param name="otherKeyToKeysCache">“参数集-Key” 的缓存管理器</param>
        /// <param name="getEntityKeysByOtherKeys">根据参数集获取Key集合的代理</param>
        /// <param name="entitiesCacheable">是否缓存实体结果集</param>
        /// <param name="getCacheKey">根据参数集获取“参数集-Key” 缓存CacheKey的代理</param>
        /// <returns></returns>
        public List<TEntity> GetEntitiesByOtherKeys(object[] otherKeys, bool keyCacheable
            , CacheEntityTable<string, List<TKey>> otherKeyToKeysCache
            , Func<object[], List<TKey>> getEntityKeysByOtherKeys
            , bool entitiesCacheable, Func<object[], string> getCacheKey)
        {
            Dictionary<TKey, TEntity> entities = new Dictionary<TKey, TEntity>();
            return GetEntitiesByOtherKeys(otherKeys, keyCacheable
                , otherKeyToKeysCache, getEntityKeysByOtherKeys
                , ref entities, entitiesCacheable, getCacheKey);
        }

        /// <summary>
        /// 根据多个参数集获取实体集合
        /// </summary>
        /// <param name="otherKeys">其它参数集合</param>
        /// <param name="keyCacheable">是否缓存Key结果</param>
        /// <param name="otherKeyToKeysCache">“参数集-Key” 的缓存管理器</param>
        /// <param name="getEntityKeysByOtherKeys">根据参数集获取Key集合的代理</param>
        /// <param name="entitiesCacheable">是否缓存实体结果集</param>
        /// <param name="getCacheKey">根据参数集获取“参数集-Key” 缓存CacheKey的代理</param>
        /// <returns></returns>
        public List<TEntity> GetEntitiesByOtherKeys(object[] otherKeys, bool keyCacheable
            , CacheEntityTable<string, List<TKey>> otherKeyToKeysCache
            , Func<object[], List<TKey>> getEntityKeysByOtherKeys
            , ref Dictionary<TKey, TEntity> entities, bool entitiesCacheable
            , Func<object[], string> getCacheKey)
        {
            if (otherKeys == null || otherKeys.Length == 0)
                return default(List<TEntity>);

            string cacheKey = getCacheKey(otherKeys);

            List<TKey> keys = default(List<TKey>);
            bool isKeysExists = false;
            if (keyCacheable && otherKeyToKeysCache.TryGetValue(cacheKey, out keys)) // 首先从Cache中查询Keys
            {
                isKeysExists = true;
            }

            if (!isKeysExists) // 如果Cache中没有Keys或者不从Cache中读取
            {
                keys = getEntityKeysByOtherKeys(otherKeys); // 从数据库中查询Keys

                if (keys != default(List<TKey>))
                {
                    otherKeyToKeysCache.Cache(cacheKey, keys); // 如果查询出来，插入Cache
                    isKeysExists = true;
                }
                else
                {
                    return default(List<TEntity>); // 从数据库中查询失败
                }
            }

            if (isKeysExists)
            {
                return GetEntities(keys.ToArray(), ref entities, entitiesCacheable); //通过Keys查找实体集合
            }
            return default(List<TEntity>);
        }


        public PagedResult<TEntity> GetEntitySet<TEntityQuery>(PagingInfo pagingInfo, TEntityQuery query
            , GetEntityKeysDelegate<TKey, TEntityQuery> getIds)
            where TEntityQuery : EntityQuery
        {
            string cacheKey = string.Format("GetEntityKeys-{0}", query.GetCacheKey());
            List<TKey> ids = null;
            if (query.KeysCacheable)
                ids = CacheHelper.Get(cacheKey.ToString()) as List<TKey>;

            if (ids == null)
            {
                ids = getIds(query);
                CacheHelper.Insert(cacheKey.ToString(), ids, CacheHelper.SecondFactorCalculate(query.KeysCacheDuration));
            }

            return EntitiesCache.GetEntitySet(ids, pagingInfo.Index,
                pagingInfo.Size, query.EntitiesCacheable
                , new GetEntitiesFromDatabaseDelegate<TKey, TEntity>(getEntitiesFromDatabase));
        }
        #endregion

        #region CUD With Validate

        /// <summary>
        /// 创建实体数据
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="validate"></param>
        /// <param name="createEntity"></param>
        /// <returns></returns>
        public ModelResult<TEntity> CreateEntity(TEntity entity, Func<TEntity, ValidationState> validate
            , Func<TEntity, ValidationState> createEntity)
        {
            string className = typeof(TEntity).Name;
            if (pluginEngine != null)
            {
                entity = pluginEngine.Process<TEntity>(string.Format("ProcessInputOf{0}", className), entity);
                entity = pluginEngine.Process<TEntity>(string.Format("ProcessInputOf{0}OnAdd", className), entity);
                pluginEngine.ExecuteAll(string.Format("Before{0}Create", className), new { entity });
            }

            ValidationStateDictionary validationStateDictionary = new ValidationStateDictionary();

            ValidationState state = validate(entity);
            if (pluginEngine != null)
            {
                pluginEngine.ExecuteAll(string.Format("{0}Validated", className), new { entity, state });
                pluginEngine.ExecuteAll(string.Format("{0}ValidatedOnAdd", className), new { entity, state });
            }
            validationStateDictionary.Add(typeof(TEntity), state);
            if (!validationStateDictionary.IsValid) 
                return new ModelResult<TEntity>(validationStateDictionary);

            ValidationState createState = createEntity(entity);
            if (pluginEngine != null)
            {
                pluginEngine.ExecuteAll(string.Format("After{0}Create", className), new { createState, entity });
            }

            state.Merge(createState);
            if (!validationStateDictionary.IsValid)
                return new ModelResult<TEntity>(validationStateDictionary);

            if (pluginEngine != null)
            {
                pluginEngine.ExecuteAll(string.Format("{0}Saved", className), new { entity });
            }

            return new ModelResult<TEntity>(entity, validationStateDictionary);
        }
        
        /// <summary>
        /// 更新实体
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="validate"></param>
        /// <param name="updateEntity"></param>
        /// <returns></returns>
        public ModelResult<TEntity> UpdateEntity(TEntity entity
            , Func<TEntity, ValidationState> validate
            , Func<TEntity, ValidationState> updateEntity)
        {
            string className = typeof(TEntity).Name;
            if (pluginEngine != null)
            {
                entity = pluginEngine.Process<TEntity>(string.Format("ProcessInputOf{0}", className), entity);
                entity = pluginEngine.Process<TEntity>(string.Format("ProcessInputOf{0}OnUpdate", className), entity);
                pluginEngine.ExecuteAll(string.Format("Before{0}Update", className), new { entity });
            }

            ValidationStateDictionary validationState = new ValidationStateDictionary();
            ValidationState state = validate(entity);
            if (pluginEngine != null)
            {
                pluginEngine.ExecuteAll(string.Format("{0}Validated", className), new { entity, state });
                pluginEngine.ExecuteAll(string.Format("{0}ValidatedOnUpdate", className), new { entity, state });
            }
            validationState.Add(typeof(TEntity), state);
            if (!validationState.IsValid)
                return new ModelResult<TEntity>(validationState);

            EntitiesCache.Remove(entity.EntityKey);

            ValidationState updateState = updateEntity(entity);
            if (pluginEngine != null)
            {
                pluginEngine.ExecuteAll(string.Format("After{0}Update", className), new { updateState, entity });
            }

            state.Merge(updateState);
            if (!validationState.IsValid)
                return new ModelResult<TEntity>(validationState);

            if (pluginEngine != null)
            {
                pluginEngine.ExecuteAll(string.Format("{0}Saved", className), new { entity });
                pluginEngine.ExecuteAll(string.Format("After{0}Update", className), new { entity });
            }

            return new ModelResult<TEntity>(entity, validationState);
        }

        /// <summary>
        /// 删除实体
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="deleteEntity"></param>
        public ModelResult<TEntity> DeleteEntity(TEntity entity,
            Func<TEntity, ValidationState> deleteEntity)
        {
            string className = typeof(TEntity).Name;
            if (pluginEngine != null)
            {
                pluginEngine.ExecuteAll(string.Format("Before{0}Delete", className), new { entity });
            }
            if (entity == null)
                throw new ArgumentNullException("entity");

            ValidationStateDictionary validationState = new ValidationStateDictionary();
            EntitiesCache.Remove(entity.EntityKey);
            ValidationState state = deleteEntity(entity);
            validationState.Add(typeof(TEntity), state);

            if (pluginEngine != null)
            {
                pluginEngine.ExecuteAll(string.Format("After{0}Delete", className), new { state, entity });
            }

            if (!validationState.IsValid)
                return new ModelResult<TEntity>(validationState);

            if (pluginEngine != null)
            {
                pluginEngine.ExecuteAll(string.Format("{0}Deleted", className), new { entity });
            }

            return new ModelResult<TEntity>(entity, validationState);
        }

        
        #endregion

        #region Remove Cache


        /// <summary>
        /// 移除缓存项
        /// </summary>
        /// <param name="key">待移除实体项的Key</param>
        public void RemoveCache(TEntity entity)
        {
            if (entity == null)
                return;
            entitiesCache.Remove(entity.EntityKey);
        }

        /// <summary>
        /// 移除缓存项
        /// </summary>
        /// <param name="key">待移除实体项的Key</param>
        public void RemoveCache(TKey key)
        {
            entitiesCache.Remove(key);
        }

        /// <summary>
        /// 移除所有实体缓存项
        /// </summary>
        public void ClearCache()
        {
            entitiesCache.RemoveAll();
        }

        #endregion

        #region CUD Without Validate

        /// <summary>
        /// 创建实体数据，不验证
        /// </summary>
        /// <param name="entity">待创建对象</param>
        /// <param name="createEntity">创建方法</param>
        /// <returns></returns>
        public TEntity CreateEntity(TEntity entity, Func<TEntity, TEntity> createEntity)
        {
            string className = typeof(TEntity).Name;
            if (pluginEngine != null)
            {
                entity = pluginEngine.Process<TEntity>(string.Format("ProcessInputOf{0}", className), entity);
                entity = pluginEngine.Process<TEntity>(string.Format("ProcessInputOf{0}OnAdd", className), entity);
                pluginEngine.ExecuteAll(string.Format("Before{0}Create", className), new { entity });
            }

            TEntity result = createEntity(entity);
            if (pluginEngine != null)
            {
                pluginEngine.ExecuteAll(string.Format("After{0}Create", className), new { entity });
            }

            if (pluginEngine != null)
            {
                pluginEngine.ExecuteAll(string.Format("{0}Saved", className), new { entity });
            }

            EntitiesCache.Cache(result.EntityKey, result);

            return result;
        }

        /// <summary>
        /// 更新实体
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="validate"></param>
        /// <param name="updateEntity"></param>
        /// <returns></returns>
        public bool UpdateEntity(TEntity entity, Action<TEntity> updateEntity)
        {
            string className = typeof(TEntity).Name;
            if (pluginEngine != null)
            {
                entity = pluginEngine.Process<TEntity>(string.Format("ProcessInputOf{0}", className), entity);
                entity = pluginEngine.Process<TEntity>(string.Format("ProcessInputOf{0}OnUpdate", className), entity);
                pluginEngine.ExecuteAll(string.Format("Before{0}Update", className), new { entity });
            }

            updateEntity(entity);

            if (pluginEngine != null)
            {
                pluginEngine.ExecuteAll(string.Format("After{0}Update", className), new { entity });
            }

            if (pluginEngine != null)
            {
                pluginEngine.ExecuteAll(string.Format("{0}Saved", className), new { entity });
                pluginEngine.ExecuteAll(string.Format("After{0}Update", className), new { entity });
            }

            EntitiesCache.Cache(entity.EntityKey, entity);

            return true;
        }
        
        /// <summary>
        /// 删除实体
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="deleteEntity"></param>
        public bool DeleteEntity(TKey key, Action<TKey> deleteEntity)
        {
            string className = typeof(TEntity).Name;
            if (pluginEngine != null)
            {
                pluginEngine.ExecuteAll(string.Format("Before{0}Delete", className), new { key });
            }
            if (key == null)
                throw new ArgumentNullException("entity");

            deleteEntity(key);
            EntitiesCache.Remove(key);

            if (pluginEngine != null)
            {
                pluginEngine.ExecuteAll(string.Format("After{0}Delete", className), new { key });
            }

            if (pluginEngine != null)
            {
                pluginEngine.ExecuteAll(string.Format("{0}Deleted", className), new { key });
            }

            return true;
        }

        #region Transaction

        /// <summary>
        /// 创建实体数据，不验证
        /// </summary>
        /// <param name="entity">待创建对象</param>
        /// <param name="createEntity">创建方法</param>
        /// <returns></returns>
        public TEntity CreateEntity(TEntity entity, TransactionManager trans, Func<TEntity, SqlTransaction, TEntity> createEntity)
        {
            string className = typeof(TEntity).Name;
            if (pluginEngine != null)
            {
                entity = pluginEngine.Process<TEntity>(string.Format("ProcessInputOf{0}", className), entity);
                entity = pluginEngine.Process<TEntity>(string.Format("ProcessInputOf{0}OnAdd", className), entity);
                pluginEngine.ExecuteAll(string.Format("Before{0}Create", className), new { entity });
            }

            TEntity result = createEntity(entity, trans.transaction);
            if (pluginEngine != null)
            {
                pluginEngine.ExecuteAll(string.Format("After{0}Create", className), new { entity });
            }

            if (pluginEngine != null)
            {
                pluginEngine.ExecuteAll(string.Format("{0}Saved", className), new { entity });
            }

            EntitiesCache.Cache(result.EntityKey, result);

            return result;
        }

        /// <summary>
        /// 更新实体
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="validate"></param>
        /// <param name="updateEntity"></param>
        /// <returns></returns>
        public bool UpdateEntity(TEntity entity, TransactionManager trans, Action<TEntity, SqlTransaction> updateEntity)
        {
            string className = typeof(TEntity).Name;
            if (pluginEngine != null)
            {
                entity = pluginEngine.Process<TEntity>(string.Format("ProcessInputOf{0}", className), entity);
                entity = pluginEngine.Process<TEntity>(string.Format("ProcessInputOf{0}OnUpdate", className), entity);
                pluginEngine.ExecuteAll(string.Format("Before{0}Update", className), new { entity });
            }

            updateEntity(entity,trans.transaction);

            if (pluginEngine != null)
            {
                pluginEngine.ExecuteAll(string.Format("After{0}Update", className), new { entity });
            }

            if (pluginEngine != null)
            {
                pluginEngine.ExecuteAll(string.Format("{0}Saved", className), new { entity });
                pluginEngine.ExecuteAll(string.Format("After{0}Update", className), new { entity });
            }

            EntitiesCache.Cache(entity.EntityKey, entity);

            return true;
        }

        /// <summary>
        /// 删除实体
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="deleteEntity"></param>
        public bool DeleteEntity(TKey key, TransactionManager trans, Action<TKey, SqlTransaction> deleteEntity)
        {
            string className = typeof(TEntity).Name;
            if (pluginEngine != null)
            {
                pluginEngine.ExecuteAll(string.Format("Before{0}Delete", className), new { key });
            }
            if (key == null)
                throw new ArgumentNullException("entity");

            deleteEntity(key, trans.transaction);
            EntitiesCache.Remove(key);

            if (pluginEngine != null)
            {
                pluginEngine.ExecuteAll(string.Format("After{0}Delete", className), new { key });
            }

            if (pluginEngine != null)
            {
                pluginEngine.ExecuteAll(string.Format("{0}Deleted", className), new { key });
            }

            return true;
        }

        #endregion

        #endregion

        #endregion
    }
}
